#include "decoding.h"
#include "vector"
#include <iostream>
//#include <functional>

extern "C" {

    #include <postgres.h>
    #include <string.h>
    #include <fmgr.h>
    #include <funcapi.h>
    #include <utils/array.h>

    PG_MODULE_MAGIC; // МАГИЯ
    //vector<double> v(0);
}
    extern "C" {

    PG_FUNCTION_INFO_V1(least_squares_polynom_array); //Вызов версии 1
    /*!
     * \brief least_squares_polynom_array расчитывает полином методом наименьших квадратов
     *
     * \param x_array массив double precision[] первых координат узлов интерполяции
     * \param y_array массив double precision[] вторых координат узлов интерполяции
     * \param gh_size количество элементов в каждом из массивов x_array и y_array. Типа bigint
     * \param poly_pow старшая степень, которая будет у выходного полинома. Типа integer. Если этот аргумент отсутствует функция подбирает степень с оптимальной ошибкой аппроксимации
     * \return возвращает массив коэффициентов полинома типа double precision[], где индекс в массиве соответствует степени полинома
     */
    Datum least_squares_polynom_array(PG_FUNCTION_ARGS) //Объявление самой функци
    {
        double *x_data;
        double *y_data;
        double *res_data;
        ArrayType *x_array = PG_GETARG_ARRAYTYPE_P(0);
        ArrayType *y_array = PG_GETARG_ARRAYTYPE_P(1);
        int gh_size = PG_GETARG_INT64(2);
        int poly_pow = PG_GETARG_INT32(3);
        // Получение указателя на данные массива
        x_data = (double *)ARR_DATA_PTR(x_array);
        y_data = (double *)ARR_DATA_PTR(y_array);
        Approx *ap = new Approx();
        if(poly_pow)
        {
            ap->least_squares_arr(x_data, y_data, gh_size, poly_pow);
        }
        else
        {
            ap->least_squares_auto_pow(x_data, y_data, gh_size);
        }
        res_data = (double *) palloc(sizeof(double) * (ap->get_poly_size()));
        ap->get_poly(res_data);

        ArrayType *res_arr;
        res_arr = construct_array((Datum *) res_data, ap->get_poly_size(), ARR_ELEMTYPE(y_array), sizeof(double), true, 'd');

        pfree(res_data);
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(legendre_polynom_array);
    /*!
     * \brief legendre_polynom_array расчитывает полином методом ортогональных полиномов Лежандра
     *
     * \param x_array массив double precision[] первых координат узлов интерполяции
     * \param y_array массив double precision[] вторых координат узлов интерполяции
     * \param gh_size количество элементов в каждом из массивов x_array и y_array. Типа bigint
     * \param poly_pow старшая степень, которая будет у выходного полинома. Типа integer. Если этот аргумент отсутствует функция подбирает степень с оптимальной ошибкой аппроксимации
     * \return возвращает массив коэффициентов полинома типа double precision[], где индекс в массиве соответствует степени полинома
     */
    Datum legendre_polynom_array(PG_FUNCTION_ARGS)
    {
        double *x_data;
        double *y_data;
        double *res_data;
        ArrayType *x_array = PG_GETARG_ARRAYTYPE_P(0);
        ArrayType *y_array = PG_GETARG_ARRAYTYPE_P(1);
        int gh_size = PG_GETARG_INT64(2);
        int poly_pow = PG_GETARG_INT32(3);
        // Получение указателя на данные массива
        x_data = (double *)ARR_DATA_PTR(x_array);
        y_data = (double *)ARR_DATA_PTR(y_array);
        Approx *ap = new Approx();
        if(poly_pow)
        {
            ap->legendre_approx_arr(x_data, y_data, gh_size, poly_pow);
        }
        else
        {
            ap->legendre_approx_auto_pow(x_data, y_data, gh_size);
        }
        res_data = (double *) palloc(sizeof(double) * (ap->get_poly_size()));
        ap->get_poly(res_data);

        ArrayType *res_arr;
        res_arr = construct_array((Datum *) res_data, ap->get_poly_size(), ARR_ELEMTYPE(y_array), sizeof(double), true, 'd');

        pfree(res_data);
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(calc_values_by_polynom);
    /*!
     * \brief calc_values_by_polynom расчитывает значения c помощью полинома
     *
     * \param x_array входной массив значений double precision[]
     * \param poly_array массив коэффициентов полинома типа double precision[], где индекс в массиве соответствует степени полинома
     * \param x_size количество элементов в массиве x_array. Типа bigint
     * \param poly_size количество элементов в массиве poly_array. Типа bigint
     * \return возвращает массив расчитанных значений типа double precision[]
     */
    Datum calc_values_by_polynom(PG_FUNCTION_ARGS)
    {
        ArrayType *x_array = PG_GETARG_ARRAYTYPE_P(0);
        ArrayType *poly_array = PG_GETARG_ARRAYTYPE_P(1);
        int x_size = PG_GETARG_INT64(2);
        int poly_size = PG_GETARG_INT64(3);
        double *x_data;
        double *poly_data;
        double *res_data;
        res_data = (double *) palloc(sizeof(double) * (x_size));
        ArrayType *res_arr;
        x_data = (double *)ARR_DATA_PTR(x_array);
        poly_data = (double *)ARR_DATA_PTR(poly_array);
        Approx *ap = new Approx();
        ap->set_poly(poly_data, poly_size);
        ap->calc_polynom_func(x_data, res_data, x_size);

        res_arr = construct_array((Datum *) res_data, x_size, ARR_ELEMTYPE(x_array), sizeof(double), true, 'd');
        pfree(res_data);
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(calc_value_by_polynom);
    /*!
     * \brief calc_values_by_polynom расчитывает значение c помощью полинома
     *
     * \param poly_array массив коэффициентов полинома типа double precision[], где индекс в массиве соответствует степени полинома
     * \param poly_size количество элементов в массиве poly_array. Типа bigint
     * \param x входное значение. Типа integer
     * \return возвращает расчитанное значение типа double precision
     */
    Datum calc_value_by_polynom(PG_FUNCTION_ARGS)
    {
        ArrayType *poly_array = PG_GETARG_ARRAYTYPE_P(0);
        int poly_size = PG_GETARG_INT64(1);
        double x = PG_GETARG_FLOAT8(2);
        double *poly_data;
        poly_data = (double *)ARR_DATA_PTR(poly_array);
        PG_RETURN_FLOAT8(approx::calc_polynom_point(poly_data, poly_size, x));
    }

    PG_FUNCTION_INFO_V1(lineal_pices);
    /*!
     * \brief lineal_pices расчитывает коэффициенты методом кусочно-линейной аппроксимации
     *
     * \param x_array массив double precision[] первых координат узлов интерполяции
     * \param y_array массив double precision[] вторых координат узлов интерполяции
     * \param input_size количество элементов в каждом из массивов x_array и y_array. Типа bigint
     * \return возвращает массив с парами коэффициентов полинома типа double precision[], где На чётных индексах k0, на нечётных k1
     */
    Datum lineal_pices(PG_FUNCTION_ARGS)
    {
        ArrayType *x_array = PG_GETARG_ARRAYTYPE_P(0);
        ArrayType *y_array = PG_GETARG_ARRAYTYPE_P(1);
        int input_size = PG_GETARG_INT64(2);
        double *x_data;
        double *y_data;
        double *res_data = (double *) palloc(sizeof(double) * (input_size * 2));
        ArrayType *res_arr;
        x_data = (double *)ARR_DATA_PTR(x_array);
        y_data = (double *)ARR_DATA_PTR(y_array);

        Approx *ap = new Approx();
        ap->lineal_pices(x_data, y_data, input_size);
        ap->get_koefs(res_data);

        res_arr = construct_array((Datum *) res_data, input_size * 2, ARR_ELEMTYPE(x_array), sizeof(double), true, 'd');
        pfree(res_data);
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(lineal_calc_values);
    /*!
     * \brief lineal_calc_values расчитывает значения c помощью кусочно-линейной функции
     *
     * \param x_array входной массив значений double precision[]
     * \param x_size количество элементов в массиве x_array. Типа bigint
     * \param lineal_koefs массив с парами коэффициентов полинома типа double precision[], где На чётных индексах k0, на нечётных k1
     * \param borders массив double precision[], хранящий границы действия коэффициентов
     * \param borders_count количество элементов в массиве borders. Типа bigint
     * \return возвращает массив расчитанных значений типа double precision[]
     */
    Datum lineal_calc_values(PG_FUNCTION_ARGS)
    {
        ArrayType *x_array = PG_GETARG_ARRAYTYPE_P(0);
        int x_size = PG_GETARG_INT64(1);
        ArrayType *lineal_koefs = PG_GETARG_ARRAYTYPE_P(2);
        ArrayType *borders = PG_GETARG_ARRAYTYPE_P(3);
        int borders_count = PG_GETARG_INT64(4);
        double *res_data = (double *) palloc(sizeof(double) * (x_size));
        double *x_data = (double *)ARR_DATA_PTR(x_array);
        double *lineal_koefs_data = (double *)ARR_DATA_PTR(lineal_koefs);
        double *borders_data = (double *)ARR_DATA_PTR(borders);
        //ArrayType *res_arr = construct_array((Datum *) res_data, x_size, ARR_ELEMTYPE(x_array), sizeof(double), true, 'd');
        //PG_RETURN_ARRAYTYPE_P(res_arr);

        Approx *ap = new Approx();
        ap->set_koefs(lineal_koefs_data, borders_data, borders_count);
        ap->calc_split_lineal(x_data, res_data, x_size);
        ArrayType *res_arr = construct_array((Datum *) res_data, x_size, ARR_ELEMTYPE(x_array), sizeof(double), true, 'd');
        pfree(res_data);
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(lineal_calc_value);
    /*!
     * \brief lineal_calc_value расчитывает значение c помощью кусочно-линейной функции
     *
     * \param lineal_koefs массив с парами коэффициентов полинома типа double precision[], где На чётных индексах k0, на нечётных k1
     * \param borders массив double precision[], хранящий границы действия коэффициентов
     * \param borders_count количество элементов в массиве borders. Типа bigint
     * \param x входное значение. Типа integer
     * \return возвращает расчитанное значение типа double precision
     */
    Datum lineal_calc_value(PG_FUNCTION_ARGS)
    {
        ArrayType *lineal_koefs = PG_GETARG_ARRAYTYPE_P(0);
        ArrayType *borders = PG_GETARG_ARRAYTYPE_P(1);
        int borders_count = PG_GETARG_INT64(2);
        double x = PG_GETARG_FLOAT8(3);
        double *lineal_koefs_data = (double *)ARR_DATA_PTR(lineal_koefs);
        double *borders_data = (double *)ARR_DATA_PTR(borders);
        PG_RETURN_FLOAT8(approx::calc_lineal_point(lineal_koefs_data, borders_data, borders_count, x));
    }


    void copy_arr(double *data, double *storage, int count)
    {
        for(int i = 0; i < count; i++)
        {
            storage[i] += data[i];
        }
    }

    PG_FUNCTION_INFO_V1(MODX5);
    /*!
     * \brief MODX5 преобразование входного массива умножением каждого элемента на три коеффициента
     *
     * \param input входной массив double precision[]
     * \param input_count количество значений входного массива. Типа bigint
     * \param k1, k2, k3 три коэффициента. Типа double precision
     * \return возвращает расчитанное значение типа double precision[]
     */
    Datum MODX5(PG_FUNCTION_ARGS)
    {
        ArrayType *input = PG_GETARG_ARRAYTYPE_P(0);
        int input_count = PG_GETARG_INT64(1);
        double K1 = PG_GETARG_FLOAT8(2);
        double K2 = PG_GETARG_FLOAT8(3);
        double K3 = PG_GETARG_FLOAT8(4);
        double *input_data = (double *)ARR_DATA_PTR(input);
        double *res_data = (double *) palloc(sizeof(double) * (input_count));
        copy_arr(input_data, res_data, input_count);
        MODGH::x5(res_data, input_count, K1, K2, K3);
        ArrayType *res_arr = construct_array((Datum *) res_data, input_count, ARR_ELEMTYPE(input), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODX6);
    /*!
     * \brief MODX6 преобразование входного массива сложением каждого элемента с тремя аргументами
     *
     * \param input входной массив double precision[]
     * \param input_count количество значений входного массива. Типа bigint
     * \param с1, с2, с3 три входных аргумента. Типа double precision
     * \return возвращает расчитанное значение типа double precision[]
     */
    Datum MODX6(PG_FUNCTION_ARGS)
    {
        ArrayType *input = PG_GETARG_ARRAYTYPE_P(0);
        int input_count = PG_GETARG_INT64(1);
        double c1 = PG_GETARG_FLOAT8(2);
        double c2 = PG_GETARG_FLOAT8(3);
        double c3 = PG_GETARG_FLOAT8(4);
        double *input_data = (double *)ARR_DATA_PTR(input);
        double *res_data = (double *) palloc(sizeof(double) * (input_count));
        copy_arr(input_data, res_data, input_count);
        MODGH::x6(res_data, input_count, c1, c2, c3);
        ArrayType *res_arr = construct_array((Datum *) res_data, input_count, ARR_ELEMTYPE(input), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODX7);
    /*!
     * \brief MODX7 преобразование входного массива делением каждого элемента на три коеффициента
     *
     * \param input входной массив double precision[]
     * \param input_count количество значений входного массива. Типа bigint
     * \param g1, g2, g3 три коеффициента. Типа double precision
     * \return возвращает расчитанное значение типа double precision[]
     */
    Datum MODX7(PG_FUNCTION_ARGS)
    {
        ArrayType *input = PG_GETARG_ARRAYTYPE_P(0);
        int input_count = PG_GETARG_INT64(1);
        double g1 = PG_GETARG_FLOAT8(2);
        double g2 = PG_GETARG_FLOAT8(3);
        double g3 = PG_GETARG_FLOAT8(4);
        double *input_data = (double *)ARR_DATA_PTR(input);
        double *res_data = (double *) palloc(sizeof(double) * (input_count));
        copy_arr(input_data, res_data, input_count);
        MODGH::x7(res_data, input_count, g1, g2, g3);
        ArrayType *res_arr = construct_array((Datum *) res_data, input_count, ARR_ELEMTYPE(input), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODY1);
    /*!
     * \brief MODY1 преобразование входного массива делением каждого элемента на коеффициент
     *
     * \param input входной массив double precision[]
     * \param input_count количество значений входного массива. Типа bigint
     * \param Kp коеффициент для деления. Типа double precision
     * \return возвращает расчитанное значение типа double precision[]
     */
    Datum MODY1(PG_FUNCTION_ARGS)
    {
        ArrayType *input = PG_GETARG_ARRAYTYPE_P(0);
        int input_count = PG_GETARG_INT64(1);
        double Kp = PG_GETARG_FLOAT8(2);
        double *input_data = (double *)ARR_DATA_PTR(input);
        double *res_data = (double *) palloc(sizeof(double) * (input_count));
        copy_arr(input_data, res_data, input_count);
        MODGH::y1(res_data, input_count, Kp);
        ArrayType *res_arr = construct_array((Datum *) res_data, input_count, ARR_ELEMTYPE(input), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODY2);
    /*!
     * \brief MODY2 преобразование входного массива сложением каждого элемента с аргументом
     *
     * \param input входной массив double precision[]
     * \param input_count количество значений входного массива. Типа bigint
     * \param Dp аргумент для сложения. Типа double precision
     * \return возвращает расчитанное значение типа double precision[]
     */
    Datum MODY2(PG_FUNCTION_ARGS)
    {
        ArrayType *input = PG_GETARG_ARRAYTYPE_P(0);
        int input_count = PG_GETARG_INT64(1);
        double Dp = PG_GETARG_FLOAT8(2);
        double *input_data = (double *)ARR_DATA_PTR(input);
        double *res_data = (double *) palloc(sizeof(double) * (input_count));
        copy_arr(input_data, res_data, input_count);
        MODGH::y2(res_data, input_count, Dp);
        ArrayType *res_arr = construct_array((Datum *) res_data, input_count, ARR_ELEMTYPE(input), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODY3);
    /*!
     * \brief MODY3 преобразование входного массива умножением каждого элемента на коеффициент
     *
     * \param input входной массив double precision[]
     * \param input_count количество значений входного массива. Типа bigint
     * \param Kp коеффициент для умножения. Типа double precision
     * \return возвращает расчитанное значение типа double precision[]
     */
    Datum MODY3(PG_FUNCTION_ARGS)
    {
        ArrayType *input = PG_GETARG_ARRAYTYPE_P(0);
        int input_count = PG_GETARG_INT64(1);
        double nn = PG_GETARG_FLOAT8(2);
        double *input_data = (double *)ARR_DATA_PTR(input);
        double *res_data = (double *) palloc(sizeof(double) * (input_count));
        copy_arr(input_data, res_data, input_count);
        MODGH::y3(res_data, input_count, nn);
        ArrayType *res_arr = construct_array((Datum *) res_data, input_count, ARR_ELEMTYPE(input), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODY4);
    /*!
     * \brief MODY4 преобразование входного массива по формуле Pi = (Pi - d)/k
     *
     * \param input входной массив double precision[]
     * \param input_count количество значений входного массива. Типа bigint
     * \param d исходный уровень. Типа double precision
     * \param k коеффициент трансформации. Типа double precision
     * \return возвращает расчитанное значение типа double precision[]
     */
    Datum MODY4(PG_FUNCTION_ARGS)
    {
        ArrayType *input = PG_GETARG_ARRAYTYPE_P(0);
        int input_count = PG_GETARG_INT64(1);
        double d = PG_GETARG_FLOAT8(2);
        double k = PG_GETARG_FLOAT8(3);
        double *input_data = (double *)ARR_DATA_PTR(input);
        double *res_data = (double *) palloc(sizeof(double) * (input_count));
        copy_arr(input_data, res_data, input_count);
        MODGH::y4(res_data, input_count, d, k);
        ArrayType *res_arr = construct_array((Datum *) res_data, input_count, ARR_ELEMTYPE(input), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODX1);
    /*!
     * \brief MODX1 В результате преобразования данным модулем выходной величины основного преобразователя получается выходная величина основного преобразователя в процентах
     *
     * \param input входной массив double precision[]
     * \param input_count количество значений входного массива. Типа bigint
     * \param Ub входной коеффициент. Типа double precision
     * \return возвращает расчитанное значение типа double precision[]
     */
    Datum MODX1(PG_FUNCTION_ARGS)
    {
        ArrayType *input = PG_GETARG_ARRAYTYPE_P(0);
        int input_count = PG_GETARG_INT64(1);
        double Ub = PG_GETARG_FLOAT8(2);
        double *input_data = (double *)ARR_DATA_PTR(input);
        double *res_data = (double *) palloc(sizeof(double) * (input_count));
        copy_arr(input_data, res_data, input_count);
        MODGH::x1(res_data, input_count, Ub);
        ArrayType *res_arr = construct_array((Datum *) res_data, input_count, ARR_ELEMTYPE(input), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODX4);
    /*!
     * \brief MODX4 преобразование входного массива по формуле Ui = (Ui - d)/k
     *
     * \param input входной массив double precision[]
     * \param input_count количество значений входного массива. Типа bigint
     * \param d начальное значение. Типа double precision
     * \param k чувствительность Микрона. Типа double precision
     * \return возвращает расчитанное значение типа double precision[]
     */
    Datum MODX4(PG_FUNCTION_ARGS)
    {
        ArrayType *input = PG_GETARG_ARRAYTYPE_P(0);
        int input_count = PG_GETARG_INT64(1);
        double d = PG_GETARG_FLOAT8(2);
        double k = PG_GETARG_FLOAT8(3);
        double *input_data = (double *)ARR_DATA_PTR(input);
        double *res_data = (double *) palloc(sizeof(double) * (input_count));
        copy_arr(input_data, res_data, input_count);
        MODGH::x4(res_data, input_count, d, k);
        ArrayType *res_arr = construct_array((Datum *) res_data, input_count, ARR_ELEMTYPE(input), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODX3);
    /*!
     * \brief MODX3 модуль для ВТ1201/1202 + К25.1774.000
     *
     * \param input входной массив double precision[]
     * \param input_count количество значений входного массива. Типа bigint
     * \param f0 собственная выходная частота датчика при отсутствии входного сигнала. Типа double precision
     * \return возвращает расчитанное значение типа double precision[]
     */
    Datum MODX3(PG_FUNCTION_ARGS)
    {
        ArrayType *input = PG_GETARG_ARRAYTYPE_P(0);
        int input_count = PG_GETARG_INT64(1);
        double f0 = PG_GETARG_FLOAT8(2);
        double *input_data = (double *)ARR_DATA_PTR(input);
        double *res_data = (double *) palloc(sizeof(double) * (input_count));
        MODGH::x3(input_data, res_data, input_count, f0);
        ArrayType *res_arr = construct_array((Datum *) res_data, input_count, ARR_ELEMTYPE(input), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODX2);
    /*!
     * \brief MODX2 модуль для получения выходной величины в процентах, в случае если ГХ промежуточного преобразователя в явном виде отсутстыует
     *
     * \param input входной массив double precision[]
     * \param input_count количество значений входного массива. Типа bigint
     * \param u1, u2 искуственно созданные точки ГХ (В) усилителя. Типа double precision
     * \param v1, v2 искуственно созданные точки ГХ (мВ) усилителя. Типа double precision
     * \param Ub напряжение батареи питания. Типа double precision
     * \return возвращает расчитанное значение типа double precision[]
     */
    Datum MODX2(PG_FUNCTION_ARGS)
    {
        ArrayType *input = PG_GETARG_ARRAYTYPE_P(0);
        int input_count = PG_GETARG_INT64(1);
        double u1 = PG_GETARG_FLOAT8(2);
        double u2 = PG_GETARG_FLOAT8(3);
        double v1 = PG_GETARG_FLOAT8(4);
        double v2 = PG_GETARG_FLOAT8(5);
        double Ub = PG_GETARG_FLOAT8(6);
        double *input_data = (double *)ARR_DATA_PTR(input);
        double *res_data = (double *) palloc(sizeof(double) * (input_count));
        copy_arr(input_data, res_data, input_count);
        MODGH::x2(res_data, input_count, u1, u2, v1, v2, Ub);
        ArrayType *res_arr = construct_array((Datum *) res_data, input_count, ARR_ELEMTYPE(input), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODXY7);
    /*!
     * \brief MODX2 модуль учёта поправки физической величины
     *
     * \param inputx1, inputy1 основная ГХ основного преобразователя. Типа double precision[]
     * \param input1_count количество значений основной ГХ. Типа bigint
     * \param inputx2, inputy2 вспомогательная ГХ основного преобразователя. Типа double precision[]
     * \param input2_count количество значений вспомогательной ГХ. Типа bigint
     * \return возвращает массив коеффициентов полинома седьмой степени. Типа double precision[]
     */
    Datum MODXY7(PG_FUNCTION_ARGS)
    {
        ArrayType *inputx1 = PG_GETARG_ARRAYTYPE_P(0);
        ArrayType *inputy1 = PG_GETARG_ARRAYTYPE_P(1);
        int input1_count = PG_GETARG_INT64(2);
        ArrayType *inputx2 = PG_GETARG_ARRAYTYPE_P(3);
        ArrayType *inputy2 = PG_GETARG_ARRAYTYPE_P(4);
        int input2_count = PG_GETARG_INT64(5);
        double *inputx1_data = (double *)ARR_DATA_PTR(inputx1);
        double *inputx2_data = (double *)ARR_DATA_PTR(inputx2);
        double *inputy1_data = (double *)ARR_DATA_PTR(inputy1);
        double *inputy2_data = (double *)ARR_DATA_PTR(inputy2);
        double *res8_data = (double *) palloc(sizeof(double) * (8));
        MODGH::xy7(inputx1_data, inputy1_data, input1_count, inputx2_data, inputy2_data, input2_count, res8_data);
        ArrayType *res_arr = construct_array((Datum *) res8_data, 8, ARR_ELEMTYPE(inputx1), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }

    PG_FUNCTION_INFO_V1(MODXY8);
    /*!
     * \brief MODX2 модуль учёта усилителя
     *
     * \param inputx1, inputy1 ГХ основного преобразователя. Типа double precision[]
     * \param inputx2, inputy2 ГХ промежуточного преобразователя. Типа double precision[]
     * \param input_count размер каждой из ГХ. Типа bigint
     * \return возвращает массив коеффициентов полинома седьмой степени. Типа double precision[]
     */
    Datum MODXY8(PG_FUNCTION_ARGS)
    {
        ArrayType *inputx1 = PG_GETARG_ARRAYTYPE_P(0);
        ArrayType *inputy1 = PG_GETARG_ARRAYTYPE_P(1);
        ArrayType *inputx2 = PG_GETARG_ARRAYTYPE_P(2);
        ArrayType *inputy2 = PG_GETARG_ARRAYTYPE_P(3);
        int input_count = PG_GETARG_INT64(4);
        double *inputx1_data = (double *)ARR_DATA_PTR(inputx1);
        double *inputx2_data = (double *)ARR_DATA_PTR(inputx2);
        double *inputy1_data = (double *)ARR_DATA_PTR(inputy1);
        double *inputy2_data = (double *)ARR_DATA_PTR(inputy2);
        double *res8_data = (double *) palloc(sizeof(double) * (8));
        MODGH::xy8(inputx1_data, inputy1_data, inputx2_data, inputy2_data, input_count, res8_data);
        ArrayType *res_arr = construct_array((Datum *) res8_data, 8, ARR_ELEMTYPE(inputx1), sizeof(double), true, 'd');
        PG_RETURN_ARRAYTYPE_P(res_arr);
    }
}
